package cn.com.xinjinfu.pdoulcProduct.view;

import android.content.Context;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import com.nineoldandroids.view.ViewHelper;

/**
 * 通过ViewDragHelper实现滑动控件
 * 可以实现左右上下滑动
 * 
 * @author liujing
 * 
 */
public class DragLayoutView extends FrameLayout {

	private View mTopContent;
	private View mMainContent;
	private int mWidth;//布局展示Rect的宽度，在onsizechange方法中赋值
	private int mDragRange;//拖拽的范围
	private ViewDragHelper mDragHelper;//用于实现拖拽类
	private int mMainTop;//top
	private int mHeight;
    private float scalePercent = 1;//设置top和bottom的缩放比例，默认为1,不缩放
	private Status mStatus = Status.Close;
	private GestureDetectorCompat mDetectorCompat;//用于兼容不同的SDK的API
	
	private volatile boolean tag = true;
	public void setTag(boolean tag) {
		this.tag = tag;
	}
	public DragLayoutView(Context context) {
		this(context, null);
	}

	public DragLayoutView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}
	
	public DragLayoutView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		
		mDragHelper = ViewDragHelper.create(this, mCallBack);
		mDetectorCompat = new GestureDetectorCompat(getContext(),
				mGestureListener);

	}
	
	private boolean isDrag = true;
	/*
	 * 终止所有手势动画的时候调用，目前没有用到，使用这可以根据自己的情况而调用
	 * */
	public void setDrag(boolean isDrag) {
		this.isDrag = isDrag;
		if(isDrag){
			
			mDragHelper.abort();
		}
	}
	 /*
     * 设置缩放比例
     * */
	public void setScalePercent(float scalePercent) {
		this.scalePercent = scalePercent;
	}
	SimpleOnGestureListener mGestureListener = new SimpleOnGestureListener() {
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			Log.e("movep","distanceX----="+distanceX+"distanceY----="+distanceY);
			if((Math.abs(distanceX) > Math.abs(distanceY))&&distanceX<0&&isDrag!=false&&mStatus==Status.Close){
				return true;
			}else if((Math.abs(distanceX) > Math.abs(distanceY))&&distanceX>0&&isDrag!=false&&mStatus==Status.Open){
				return false;
			}else {
				return false;
			}
		};
	};
    /*
     * ViewDragHelper的静态内部类，处理拖拽过程中View的各种变化，还有触摸加工处理
     * */
	ViewDragHelper.Callback mCallBack = new ViewDragHelper.Callback() {
		public void onEdgeTouched(int edgeFlags, int pointerId) {
			
			
		};
		
		public void onEdgeDragStarted(int edgeFlags, int pointerId) {
			 mDragHelper.captureChildView(mMainContent, pointerId); 
		};
		// 决定child是否可被拖拽。返回true则进行拖拽。
		@Override
		public boolean tryCaptureView(View child, int pointerId) {
			return child == mMainContent || child == mTopContent;
		}

		// 当capturedChild被拖拽时而被捕获时回调的方法，activePointerId被标记，capturedChild拖拽的ＩＤ,其实就是你的MAINVIEW
		@Override
		public void onViewCaptured(View capturedChild, int activePointerId) {
			super.onViewCaptured(capturedChild, activePointerId);
			Log.e("drag", "capturedChild---------"+capturedChild+"---activePointerId-----"+activePointerId);
		}

		//此方法只是用于返回拖拽返回和View的拖拽速度问题，不用于设置
		@Override
		public int getViewHorizontalDragRange(View child) {
			return mDragRange;
		}

		//纵向拖拽试下该方法，返回在拖拽过程中Y 轴增量
		@Override
		public int clampViewPositionVertical(View child, int top, int dy) {
			// TODO Auto-generated method stub
			if (mMainTop + dy < 0) {
				return 0;
			} else if (mMainTop + dy > mDragRange) {
				return mDragRange;
			}
			return top;
		}

       //当View发生拖拽的时候，位置发生变化，自动回调此方法。		
		@Override
		public void onViewPositionChanged(View changedView, int left, int top,
				int dx, int dy) {
			//MainView
			if (changedView == mMainContent) {
				mMainTop = top;
			} else {
				mMainTop += dy;
			}

			
			if (mMainTop < 0) {
				mMainTop = 0;
			} else if (mMainTop > mDragRange) {
				mMainTop = mDragRange;
			}
			
			// changedView一般都是MainView,如果该处是TopView 那么强制布局
			if (changedView == mTopContent) {
				
				layoutContent();
			}

			dispatchDragEvent(mMainTop);

		}

		// View被释放时,侧滑打开或恢复,yvel根据Y轴的滑动方向和速率来决定界面的的更替

		@Override
		public void onViewReleased(View releasedChild, float xvel, float yvel) {
			Log.e("onlayout","---xvel---="+xvel+"---yvel--=="+yvel);
			if (yvel > 0) {
				open();
			} else if (yvel == 0 && mMainTop > mDragRange * 0.5f) {
				open();
			} else {
				close();
			}

		}

		//当拖拽状态改变的时，IDLE/DRAGGING/SETTLING
		@Override
		public void onViewDragStateChanged(int state) {
			super.onViewDragStateChanged(state);
			Log.e("flingchange","onViewDragStateChanged");
		}

	};

	private void layoutContent() {
		Log.e("layoutview","偏差的改变-----==="+mMainTop);
		mMainContent.layout(0, mMainTop, mWidth,mMainTop + mHeight);
		mTopContent.layout(0, 0, mWidth, mHeight);
	}

	/**
	 * 每次更新都会调用 根据当前执行的位置计算百分比percent：用于更main界面的按钮的操作
	 */
	protected void dispatchDragEvent(int mainLeft) {
		
		
		Log.e("moveview","偏差距离的计算---==="+mainLeft);
		float percent = mainLeft / (float) mDragRange;
		animViews(percent);

		if (mListener != null) {
			mListener.onDraging(percent);
		}

		Status lastStatus = mStatus;
		if (updateStatus(mainLeft) != lastStatus) {
			if (mListener == null) {
				return;
			}
			if (lastStatus == Status.Draging) {
				if (mStatus == Status.Close) {
					mListener.onClose();
				} else if (mStatus == Status.Open) {
					mListener.onOpen();
				}

			}
		}
	}
    /*
     * 此处提供了设置的拖拽过程中，View布局的监听回调接口
     * */
	public static interface OnLayoutDragingListener {
		void onOpen();

		void onClose();

		void onDraging(float percent);
	}

	private OnLayoutDragingListener mListener;

	public void setOnLayoutDragingListener(OnLayoutDragingListener l) {
		mListener = l;
	}

	private Status updateStatus(int mainLeft) {
		if (mainLeft == 0) {
			mStatus = Status.Close;
		} else if (mainLeft == mDragRange) {
			mStatus = Status.Open;
		} else {
			mStatus = Status.Draging;
		}
		return mStatus;
	}

	
	/*
	 * 此处提供界面的三种状态的接口
	 * */
	public static enum Status {
		Open, Close, Draging
	}

	public Status getStatus() {
		return mStatus;
	}

	public void setStatus(Status mStatus) {
		this.mStatus = mStatus;
	}
	
	/**
	 * 伴随动画：通过设置缩放的比例来改变的界面显示的状态
	 *
	 */
	private void animViews(float percent) {
		// 主面板：缩放
//		float inverse = 1 - percent * 0.2f;
		ViewHelper.setScaleX(mMainContent, scalePercent);
		ViewHelper.setScaleY(mMainContent, scalePercent);

		// 左面板：缩放、平移、透明度
		ViewHelper.setScaleX(mTopContent, 0.5f + 0.5f * percent);
		ViewHelper.setScaleY(mTopContent, 0.5f + 0.5f * percent);

		ViewHelper.setTranslationY(mTopContent, -mWidth / 2.0f + mWidth / 2.0f
				* percent);
		ViewHelper.setAlpha(mTopContent, percent);
		//要是改变背景色的调用setbackGroundFilter（float），我暂时没有做，你也用不到
	}
	
	/*
	 * 设置背景的渐变色,这是PorterDuff.Mode.SRC_OVER覆盖的一种模式，你要是想看 就看一下这个PorterDuff
	 * */
	public void setbackGroundFilter(float percent){
		// 背景：颜色渐变
				getBackground().setColorFilter(
						evaluate(percent, Color.BLACK, Color.TRANSPARENT),
						PorterDuff.Mode.SRC_OVER);
	}
    /*
     * 此处是颜色通道的计算ＡＲＧＢ,
     * */
	private int evaluate(float fraction, int startValue, int endValue) {
		int startInt = (Integer) startValue;
		int startA = (startInt >> 24) & 0xff;
		int startR = (startInt >> 16) & 0xff;
		int startG = (startInt >> 8) & 0xff;
		int startB = startInt & 0xff;

		int endInt = (Integer) endValue;
		int endA = (endInt >> 24) & 0xff;
		int endR = (endInt >> 16) & 0xff;
		int endG = (endInt >> 8) & 0xff;
		int endB = endInt & 0xff;

		return (int) ((startA + (int) (fraction * (endA - startA))) << 24)
				| (int) ((startR + (int) (fraction * (endR - startR))) << 16)
				| (int) ((startG + (int) (fraction * (endG - startG))) << 8)
				| (int) ((startB + (int) (fraction * (endB - startB))));
	}
    /*
     *1.把当前的拦截时间提供给手势识别的onTouchEvent事件
     *2.提供给父类的优化拦截方法shouldInterceptTouchEvent判断是否拦截当时间触摸事件流
     *00000001&00000000 false  只有当00000001和00000001 true 的时间才回拦截
     * */
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		boolean onTouchEvent = mDetectorCompat.onTouchEvent(ev);
		return mDragHelper.shouldInterceptTouchEvent(ev) & onTouchEvent;
	};
	
	
	/*
	 * 在父类触摸事件中将要分发给ViewDragHelper.Callback事件回调的方法中
	 * */
	@Override
	public boolean onTouchEvent(MotionEvent event) {

		try {
			mDragHelper.processTouchEvent(event);
		} catch (Exception e) {
		}
		return true;
	}

	public void close() {
		close(true);
	};

	public void open() {
		open(true);
	}
	
	public void slowAnim() {
		
	}
    /*
     * 方法是从刚才定位的页面返回:如果关闭TOPVIEW需要调用此方法
     * */
	public void close(boolean isSmooth) {
		mMainTop = 0;
		if (isSmooth) {
			// 执行动画，返回true代表有未完成的动画, 需要继续执行，如果是纵向滑动需要更新finalTop的值
			if (mDragHelper.smoothSlideViewTo(mMainContent, 0, mMainTop)) {
				// 注意：参数传递根ViewGroup
				ViewCompat.postInvalidateOnAnimation(this);
			}
		} else {
			layoutContent();
		}
	}
    /*
     * 该方法是定位到某个页面，这个方法会随着手势就行移动，如果返回的是true那么会一直随着手势移动到指定位置，然后返回false，结束动画
     * 
     * */
	public void open(boolean isSmooth) {
		mMainTop = mDragRange;
		if (isSmooth) {
			//此处应该把l置为0,t置为滑动的距离
			if (mDragHelper.smoothSlideViewTo(mMainContent, 0, mMainTop)) {
				ViewCompat.postInvalidateOnAnimation(this);
			}
		} else {
			layoutContent();
		}
	}
    /*
     * 滑动动画触发的时候调用，使用ViewCompat进行版本兼容，postInvalidateOnAnimation提高动画的执行效率
     * */
	@Override
	public void computeScroll() {
		// 高频率调用，决定是否有下一个变动等待执行
		if (mDragHelper.continueSettling(true)) {
			ViewCompat.postInvalidateOnAnimation(this);
		}
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		Log.e("onlayout","mMainLeft--="+mMainTop+"mWidth--=="+mWidth+"--mHeight--="+mHeight);
		//这里没问题
		mMainContent.layout(0, mMainTop, mWidth,mMainTop + mHeight);
		mTopContent.layout(0, 0, mWidth, mHeight);
	}
    
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		Log.e("onFinishInflate", "onSizeChanged");
		//拿到宽高
		mWidth = getMeasuredWidth();
		mHeight = getMeasuredHeight();
		//设置拖动范围
		mDragRange = mTopContent.getMeasuredHeight();
		if(tag){
			open();
			tag = false;
		}
	}

	/**
	 * 此处是所有内存中的ViewTree全都被映射成XML的时候自动调用，然后难道我的ViewGroup中两个子View
	 */
	@Override
	protected void onFinishInflate() {

		int childCount = getChildCount();
		// 必要的检验
		if (childCount < 2) {
			throw new IllegalStateException(
					"You need two childrens in your content");
		}

		if (!(getChildAt(0) instanceof ViewGroup)
				|| !(getChildAt(1) instanceof ViewGroup)) {
			throw new IllegalArgumentException(
					"Your childrens must be an instance of ViewGroup");
		}

		mTopContent = getChildAt(0);
		mMainContent = getChildAt(1);
	}

}
